module multiply_16x16_8x8 (
		   output logic [31:0] o_product,
		   input logic [15:0]  i_a, // multiplicand
		   input logic [15:0]  i_b, // multiplier
		   input logic 		   i_sign, // 0:unsigned, 1:signed
		   input logic 		   i_mode8 // 0:16x16, 1:two 8x8
						   );
   wire 					   a_sign = i_sign & i_a[15];
   wire 					   b_sign = i_sign & i_b[15];
   wire 					   mode8 = i_mode8;
   
   wire [15+1:0] 			   a = {a_sign, i_a};
   wire [15+2:0] 			   b = {{2{b_sign}}, i_b};
   
   wire 					   a_16_sign = a_sign;
   wire 					   a_8_L_sign = i_sign & i_a[7];
   wire 					   a_8_H_sign = i_sign & i_a[15];
   wire 					   b_16_sign = b_sign;
   wire 					   b_8_L_sign = i_sign & i_b[7];
   wire 					   b_8_H_sign = i_sign & i_b[15];
   
   wire [15+1:0] 			   a_16 = a;
   wire [7+1:0] 			   a_8_L = {a_8_L_sign, i_a[7:0]};
   wire [7+1:0] 			   a_8_H = {a_8_H_sign, i_a[15:8]};
   
   wire [15+3:0] 			   b_16_ext = {b, 1'b0};
   wire [15+3:0] 		       b_8_L_ext = {b[17:8], b[7:0], 1'b0};
   wire [15+3:0] 			   b_8_H_ext = {b[17:8], 1'b0, b[6:0], 1'b0};
   wire [15+3:0] 			   b_mix_ext_0 = mode8 ? b_8_L_ext : b_16_ext;
   wire [15+3:0] 			   b_mix_ext_1 = mode8 ? b_8_H_ext : b_16_ext;
   
   wire [15+1:0] 			   a_mix_0 = mode8 ? {a_8_L_sign, a[15:9], a_8_L_sign, a[7:0]} : a[16:0]; // FIXME:the a[15:9] is no useful when in 8x8 mode
   wire [15+1:0] 			   a_mix_1 = mode8 ? {a_8_H_sign, a[15:8], 1'b0, a[6:0]} : a[16:0]; // only one bit are diff with a_mix_16  //FIXME: a[6:0] not useful in 8x8
   
   // PPs for common
   logic [15+1:0] 			   pp[8:0]; // total 9 PPs			// FIXME: pp[width/2:0]  // width/2+1
   logic 					   S[7:0]; // one less than the num of PPs
   logic 					   E[7:0];
   logic [31:0] 			   final_pp0, final_pp1;

   // ==================== generate PPs, S and E for any mode ====================
   // the low 4 PPs
   booth2_pp_gen #(16+1) mul_pp0
     (
      .pp_out(pp[0]),
      .pp_s(S[0]),
      .pp_e(E[0]),
      .mcand(a_mix_0),		// multiplicand
      .booth2(b_mix_ext_0[2:0])
      );
   
   booth2_pp_gen #(16+1) mul_pp1
     (
      .pp_out(pp[1]),
      .pp_s(S[1]),
      .pp_e(E[1]),
      .mcand(a_mix_0),
      .booth2(b_mix_ext_0[4:2])
      );

   booth2_pp_gen #(16+1) mul_pp2
     (
      .pp_out(pp[2]),
      .pp_s(S[2]),
      .pp_e(E[2]),
      .mcand(a_mix_0),
      .booth2(b_mix_ext_0[6:4])
      );

   booth2_pp_gen #(16+1) mul_pp3
     (
      .pp_out(pp[3]),
      .pp_s(S[3]),
      .pp_e(E[3]),
      .mcand(a_mix_0),
      .booth2(b_mix_ext_0[8:6])
      );


   //the high 5 PPs
   booth2_pp_gen #(16+1) mul_pp4
     (
      .pp_out(pp[4]),
      .pp_s(S[4]),
      .pp_e(E[4]),
      .mcand(a_mix_1),
      .booth2(b_mix_ext_1[10:8])
      );

   booth2_pp_gen #(16+1) mul_pp5
     (
      .pp_out(pp[5]),
      .pp_s(S[5]),
      .pp_e(E[5]),
      .mcand(a_mix_1),
      .booth2(b_mix_ext_1[12:10])
      );

   booth2_pp_gen #(16+1) mul_pp6
     (
      .pp_out(pp[6]),
      .pp_s(S[6]),
      .pp_e(E[6]),
      .mcand(a_mix_1),
      .booth2(b_mix_ext_1[14:12])
      );

   booth2_pp_gen #(16+1) mul_pp7
     (
      .pp_out(pp[7]),
      .pp_s(S[7]),
      .pp_e(E[7]),
      .mcand(a_mix_1),
      .booth2(b_mix_ext_1[16:14])
      );

   
   booth2_pp_gen #(16+1) mul_pp8
     (
      .pp_out(pp[8]),
      .pp_s(),			// the last one is not need (the last PP is 0 or positive, never negative)
      .pp_e(),
      .mcand(a_mix_1),
      .booth2(b_mix_ext_1[18:16])
      );

   // ==================== the PPs, S and E for 16x16 mode ====================
   logic [15+1:0] 		       pp_16[8:0];	// PPs for 16-bit mode
   logic 			       S_16[7:0];
   logic 			       E_16[7:0];
   
   generate
      genvar 			       i;
      for(i=0;i<=8;i++)
   	begin : mul_pps_16
	   assign pp_16[i] = pp[i];
	end
   endgenerate
   
   generate
      //      genvar 			       i;
      for(i=0;i<=7;i++)
   	begin : mul_SE_16
	   assign S_16[i] = S[i];
	   assign E_16[i] = E[i];
	end
   endgenerate
   
    
   // ==================== the PPs, S and E for 8x8 mode ====================
   logic [7+1:0] 		       pp_8_L[4:0];	//5 PPs for 8-bit mode (high 8 bits)
   logic [7+1:0] 			   pp_8_H[4:0]; 
   logic 					   S_8_L[3:0], S_8_H[3:0];
   logic 					   E_8_L[3:0], E_8_H[3:0];
   
   // PPs for low 8 bits
   assign pp_8_L[0] = pp[0][8:0];
   assign pp_8_L[1] = pp[1][8:0];
   assign pp_8_L[2] = pp[2][8:0];
   assign pp_8_L[3] = pp[3][8:0];
   
   booth2_pp_gen #(8+1) mul_pp_8_L_4
     (
      .pp_out(pp_8_L[4]),
      .pp_s(),			// not need
      .pp_e(),
      .mcand(a_8_L),		// multiplicand
      .booth2({{2{b_8_L_sign}}, b[7]})
      );
   //the S for pp_8_L
   assign S_8_L[0] = S[0];
   assign S_8_L[1] = S[1];
   assign S_8_L[2] = S[2];
   assign S_8_L[3] = S[3];
   //the E for pp_8_L
   assign E_8_L[0] = E[0];
   assign E_8_L[1] = E[1];
   assign E_8_L[2] = E[2];
   assign E_8_L[3] = E[3];
   
   //PPs for high 8 bits
   assign pp_8_H[0] = pp[4][16:8];
   assign pp_8_H[1] = pp[5][16:8];
   assign pp_8_H[2] = pp[6][16:8];
   assign pp_8_H[3] = pp[7][16:8];
   assign pp_8_H[4] = pp[8][16:8];
   //S for PP_8_H
   assign S_8_H[0] = S[4];
   assign S_8_H[1] = S[5];
   assign S_8_H[2] = S[6];
   assign S_8_H[3] = S[7];
   //the E for pp_E_H
   assign E_8_H[0] = E[4];
   assign E_8_H[1] = E[5];
   assign E_8_H[2] = E[6];
   assign E_8_H[3] = E[7];
   

   // ==================== compress ====================
   // sign compensation for mix mode : the sign bit of a_8_L * b_8_L
   assign C = ~(a[7:0]==8'h00 || b[7:0]==8'h00) & (a_8_L_sign ^ b_8_L_sign);
   
   // ==================== wires need create ====================
   logic 			       S1_1_1,S1_1_0,S1_3_1,S1_4_2,S1_5_1,S1_4_1,S1_6_2,S1_7_2,S1_7_3,S1_8_2,S1_7_1,S1_9_2,S1_9_3,S1_10_3,S1_10_4,S1_11_2,S1_11_3,S1_10_2,S1_12_3,S1_12_4,S1_13_3,S1_13_4,S1_13_5,S1_14_3,S1_14_4,S1_13_2,S1_15_3,S1_15_4,S1_15_5,S1_16_3,S1_16_4,S1_16_5,S1_17_3,S1_17_4,S1_17_5,S1_18_3,S1_18_4,S1_18_5,S1_19_3,S1_19_4,S1_19_5,S1_20_3,S1_20_4,S1_20_5,S1_21_3,S1_21_4,S1_21_5,S1_22_3,S1_22_4,S1_21_2,S1_23_2,S1_23_3,S1_22_2,S1_24_2,S1_24_3,S1_25_2,S1_25_3,S1_26_2,S1_26_3,S1_27_2,S1_27_3,S1_28_2,S1_27_1,S1_29_1,S1_28_1,S1_30_1,S1_31_1,S1_31_Carry_0;
   logic 			       S2_0_0,S2_2_1,S2_2_0,S2_4_1,S2_5_1,S2_6_1,S2_7_2,S2_8_1,S2_7_1,S2_9_2,S2_10_2,S2_9_1,S2_11_2,S2_11_3,S2_12_2,S2_11_1,S2_13_2,S2_13_3,S2_14_2,S2_14_3,S2_15_2,S2_15_3,S2_16_2,S2_16_3,S2_17_2,S2_17_3,S2_18_2,S2_18_3,S2_19_2,S2_19_3,S2_20_2,S2_20_3,S2_21_2,S2_21_3,S2_22_2,S2_22_3,S2_23_2,S2_23_3,S2_24_2,S2_23_1,S2_25_2,S2_24_1,S2_26_2,S2_25_1,S2_27_2,S2_26_1,S2_28_1,S2_27_1,S2_29_1,S2_30_1,S2_31_1,S2_31_Carry_0;
   logic 			       S3_0_0,S3_1_0,S3_3_1,S3_3_0,S3_5_1,S3_6_1,S3_7_1,S3_8_1,S3_9_1,S3_10_1,S3_11_2,S3_12_1,S3_11_1,S3_13_2,S3_14_2,S3_13_1,S3_15_2,S3_14_1,S3_16_2,S3_15_1,S3_17_2,S3_16_1,S3_18_2,S3_17_1,S3_19_2,S3_18_1,S3_20_2,S3_19_1,S3_21_2,S3_20_1,S3_22_2,S3_21_1,S3_23_2,S3_22_1,S3_24_1,S3_23_1,S3_25_1,S3_26_1,S3_27_1,S3_28_1,S3_29_1,S3_30_1,S3_31_1,S3_31_Carry_0;
   logic 			       S4_0_0,S4_1_0,S4_2_0,S4_4_1,S4_4_0,S4_6_1,S4_7_1,S4_8_1,S4_9_1,S4_10_1,S4_11_1,S4_12_1,S4_13_1,S4_14_1,S4_15_1,S4_16_1,S4_17_1,S4_18_1,S4_19_1,S4_20_1,S4_21_1,S4_22_1,S4_23_1,S4_24_1,S4_25_1,S4_26_1,S4_27_1,S4_28_1,S4_29_1,S4_30_1,S4_31_1,S4_31_Carry_0;
   // ==================== Stage1 ====================
   HA ha1 (S1_1_1,S1_0_0,pp[0][0],S[0]);
   assign S1_1_0 = pp[0][1];
   FA fa1 (S1_3_1,S1_2_0,pp[1][0],pp[0][2],S[1]);
   HA ha2 (S1_4_2,S1_3_0,pp[1][1],pp[0][3]);
   FA fa2 (S1_5_1,S1_4_0,pp[2][0],pp[1][2],pp[0][4]);
   assign S1_4_1 = S[2];
   FA fa3 (S1_6_2,S1_5_0,pp[2][1],pp[1][3],pp[0][5]);
   FA fa4 (S1_7_2,S1_6_0,pp[3][0],pp[2][2],pp[1][4]);
   HA ha3 (S1_7_3,S1_6_1,pp[0][6],S[3]);
   FA fa5 (S1_8_2,S1_7_0,pp[3][1],pp[2][3],pp[1][5]);
   assign S1_7_1 = pp[0][7];
   FA fa6 (S1_9_2,S1_8_0,pp[3][2],pp[2][4],pp[1][6]);
   FA fa7 (S1_9_3,S1_8_1,pp[0][8],(mode8 ? pp_8_L[4][0] : pp[4][0]),(~mode8 & S[4]));
   FA fa8 (S1_10_3,S1_9_0,pp[3][3],pp[2][5],pp[1][7]);
   HA ha4 (S1_10_4,S1_9_1,(mode8 ? {~E[0]} : pp[4][1]),(mode8 ? pp_8_L[4][1] : pp[0][9]));
   FA fa9 (S1_11_2,S1_10_0,pp[3][4],pp[2][6],pp[1][8]);
   FA fa10 (S1_11_3,S1_10_1,(mode8 ? {~E[0]} : pp[5][0]),(mode8 ? pp_8_L[4][2] : pp[4][2]),(~mode8 & pp[0][10]));
   assign S1_10_2 = (~mode8 & S[5]);
   FA fa11 (S1_12_3,S1_11_0,pp[3][5],pp[2][7],(mode8 ? pp_8_L[4][3] : pp[5][1]));
   FA fa12 (S1_12_4,S1_11_1,(mode8 ? E[1] : pp[4][3]),(mode8 ? E[0] : pp[1][9]),(~mode8 & pp[0][11]));
   FA fa13 (S1_13_3,S1_12_0,pp[3][6],pp[2][8],(mode8 ? pp_8_L[4][4] : pp[6][0]));
   FA fa14 (S1_13_4,S1_12_1,(mode8 ? 1'b1 : pp[5][2]),(~mode8 & pp[4][4]),(~mode8 & pp[1][10]));
   HA ha5 (S1_13_5,S1_12_2,(~mode8 & pp[0][12]),(~mode8 & S[6]));
   FA fa15 (S1_14_3,S1_13_0,pp[3][7],(mode8 ? pp_8_L[4][5] : pp[6][1]),(mode8 ? E[2] : pp[5][3]));
   FA fa16 (S1_14_4,S1_13_1,(~mode8 & pp[4][5]),(~mode8 & pp[2][9]),(~mode8 & pp[1][11]));
   assign S1_13_2 = (~mode8 & pp[0][13]);
   FA fa17 (S1_15_3,S1_14_0,pp[3][8],(mode8 ? pp_8_L[4][6] : pp[7][0]),(mode8 ? 1'b1 : pp[6][2]));
   FA fa18 (S1_15_4,S1_14_1,(~mode8 & pp[5][4]),(~mode8 & pp[4][6]),(~mode8 & pp[2][10]));
   FA fa19 (S1_15_5,S1_14_2,(~mode8 & pp[1][12]),(~mode8 & pp[0][14]),(~mode8 & S[7]));
   FA fa20 (S1_16_3,S1_15_0,(mode8 ? pp_8_L[4][7] : pp[7][1]),(mode8 ? E[3] : pp[6][3]),(~mode8 & pp[5][5]));
   FA fa21 (S1_16_4,S1_15_1,(~mode8 & pp[4][7]),(~mode8 & pp[3][9]),(~mode8 & pp[2][11]));
   HA ha6 (S1_16_5,S1_15_2,(~mode8 & pp[1][13]),(~mode8 & pp[0][15]));
   FA fa22 (S1_17_3,S1_16_0,pp[4][8],(mode8 ? S[4] : pp[8][0]),(mode8 ? C : pp[7][2]));
   FA fa23 (S1_17_4,S1_16_1,(mode8 ? 1'b1 : pp[6][4]),(~mode8 & pp[5][6]),(~mode8 & pp[3][10]));
   FA fa24 (S1_17_5,S1_16_2,(~mode8 & pp[2][12]),(~mode8 & pp[1][14]),(~mode8 & pp[0][16]));
   FA fa25 (S1_18_3,S1_17_0,pp[4][9],(mode8 ? 1'b1 : {~E[0]}),(~mode8 & pp[8][1]));
   FA fa26 (S1_18_4,S1_17_1,(~mode8 & pp[7][3]),(~mode8 & pp[6][5]),(~mode8 & pp[5][7]));
   FA fa27 (S1_18_5,S1_17_2,(~mode8 & pp[3][11]),(~mode8 & pp[2][13]),(~mode8 & pp[1][15]));
   FA fa28 (S1_19_3,S1_18_0,pp[5][8],pp[4][10],(mode8 ? S[5] : {~E[0]}));
   FA fa29 (S1_19_4,S1_18_1,(mode8 ? 1'b1 : pp[8][2]),(~mode8 & pp[7][4]),(~mode8 & pp[6][6]));
   FA fa30 (S1_19_5,S1_18_2,(~mode8 & pp[3][12]),(~mode8 & pp[2][14]),(~mode8 & pp[1][16]));
   FA fa31 (S1_20_3,S1_19_0,pp[5][9],pp[4][11],(mode8 ? 1'b1 : pp[8][3]));
   FA fa32 (S1_20_4,S1_19_1,(~mode8 & pp[7][5]),(~mode8 & pp[6][7]),(~mode8 & pp[3][13]));
   FA fa33 (S1_20_5,S1_19_2,(~mode8 & pp[2][15]),(~mode8 & E[1]),(~mode8 & E[0]));
   FA fa34 (S1_21_3,S1_20_0,pp[6][8],pp[5][10],pp[4][12]);
   FA fa35 (S1_21_4,S1_20_1,1'b1,(mode8 ? S[6] : pp[8][4]),(~mode8 & pp[7][6]));
   HA ha7 (S1_21_5,S1_20_2,(~mode8 & pp[3][14]),(~mode8 & pp[2][16]));
   FA fa36 (S1_22_3,S1_21_0,pp[6][9],pp[5][11],pp[4][13]);
   FA fa37 (S1_22_4,S1_21_1,(mode8 ? 1'b1 : pp[8][5]),(~mode8 & pp[7][7]),(~mode8 & pp[3][15]));
   assign S1_21_2 = (~mode8 & E[2]);
   FA fa38 (S1_23_2,S1_22_0,pp[7][8],pp[6][10],pp[5][12]);
   FA fa39 (S1_23_3,S1_22_1,pp[4][14],1'b1,(mode8 ? S[7] : pp[8][6]));
   assign S1_22_2 = (~mode8 & pp[3][16]);
   FA fa40 (S1_24_2,S1_23_0,pp[7][9],pp[6][11],pp[5][13]);
   FA fa41 (S1_24_3,S1_23_1,pp[4][15],(mode8 ? 1'b1 : pp[8][7]),(~mode8 & E[3]));
   FA fa42 (S1_25_2,S1_24_0,pp[8][8],pp[7][10],pp[6][12]);
   FA fa43 (S1_25_3,S1_24_1,pp[5][14],pp[4][16],1'b1);
   FA fa44 (S1_26_2,S1_25_0,pp[8][9],pp[7][11],pp[6][13]);
   HA ha8 (S1_26_3,S1_25_1,pp[5][15],E[4]);
   FA fa45 (S1_27_2,S1_26_0,pp[8][10],pp[7][12],pp[6][14]);
   HA ha9 (S1_27_3,S1_26_1,pp[5][16],1'b1);
   FA fa46 (S1_28_2,S1_27_0,pp[8][11],pp[7][13],pp[6][15]);
   assign S1_27_1 = E[5];
   FA fa47 (S1_29_1,S1_28_0,pp[8][12],pp[7][14],pp[6][16]);
   assign S1_28_1 = 1'b1;
   FA fa48 (S1_30_1,S1_29_0,pp[8][13],pp[7][15],E[6]);
   FA fa49 (S1_31_1,S1_30_0,pp[8][14],pp[7][16],1'b1);
   HA ha10 (S1_31_Carry_0,S1_31_0,pp[8][15],E[7]);
   // ==================== Stage2 ====================
   assign S2_0_0 = S1_0_0;
   HA ha11 (S2_2_1,S2_1_0,S1_1_0,S1_1_1);
   assign S2_2_0 = S1_2_0;
   HA ha12 (S2_4_1,S2_3_0,S1_3_0,S1_3_1);
   FA fa50 (S2_5_1,S2_4_0,S1_4_0,S1_4_1,S1_4_2);
   HA ha13 (S2_6_1,S2_5_0,S1_5_0,S1_5_1);
   FA fa51 (S2_7_2,S2_6_0,S1_6_0,S1_6_1,S1_6_2);
   FA fa52 (S2_8_1,S2_7_0,S1_7_0,S1_7_1,S1_7_2);
   assign S2_7_1 = S1_7_3;
   FA fa53 (S2_9_2,S2_8_0,S1_8_0,S1_8_1,S1_8_2);
   FA fa54 (S2_10_2,S2_9_0,S1_9_0,S1_9_1,S1_9_2);
   assign S2_9_1 = S1_9_3;
   FA fa55 (S2_11_2,S2_10_0,S1_10_0,S1_10_1,S1_10_2);
   HA ha14 (S2_11_3,S2_10_1,S1_10_3,S1_10_4);
   FA fa56 (S2_12_2,S2_11_0,S1_11_0,S1_11_1,S1_11_2);
   assign S2_11_1 = S1_11_3;
   FA fa57 (S2_13_2,S2_12_0,S1_12_0,S1_12_1,S1_12_2);
   HA ha15 (S2_13_3,S2_12_1,S1_12_3,S1_12_4);
   FA fa58 (S2_14_2,S2_13_0,S1_13_0,S1_13_1,S1_13_2);
   FA fa59 (S2_14_3,S2_13_1,S1_13_3,S1_13_4,S1_13_5);
   FA fa60 (S2_15_2,S2_14_0,S1_14_0,S1_14_1,S1_14_2);
   HA ha16 (S2_15_3,S2_14_1,S1_14_3,S1_14_4);
   FA fa61 (S2_16_2,S2_15_0,S1_15_0,S1_15_1,S1_15_2);
   FA fa62 (S2_16_3,S2_15_1,S1_15_3,S1_15_4,S1_15_5);
   FA fa63 (S2_17_2,S2_16_0,S1_16_0,S1_16_1,S1_16_2);
   FA fa64 (S2_17_3,S2_16_1,S1_16_3,S1_16_4,S1_16_5);
   FA fa65 (S2_18_2,S2_17_0,S1_17_0,S1_17_1,S1_17_2);
   FA fa66 (S2_18_3,S2_17_1,S1_17_3,S1_17_4,S1_17_5);
   FA fa67 (S2_19_2,S2_18_0,S1_18_0,S1_18_1,S1_18_2);
   FA fa68 (S2_19_3,S2_18_1,S1_18_3,S1_18_4,S1_18_5);
   FA fa69 (S2_20_2,S2_19_0,S1_19_0,S1_19_1,S1_19_2);
   FA fa70 (S2_20_3,S2_19_1,S1_19_3,S1_19_4,S1_19_5);
   FA fa71 (S2_21_2,S2_20_0,S1_20_0,S1_20_1,S1_20_2);
   FA fa72 (S2_21_3,S2_20_1,S1_20_3,S1_20_4,S1_20_5);
   FA fa73 (S2_22_2,S2_21_0,S1_21_0,S1_21_1,S1_21_2);
   FA fa74 (S2_22_3,S2_21_1,S1_21_3,S1_21_4,S1_21_5);
   FA fa75 (S2_23_2,S2_22_0,S1_22_0,S1_22_1,S1_22_2);
   HA ha17 (S2_23_3,S2_22_1,S1_22_3,S1_22_4);
   FA fa76 (S2_24_2,S2_23_0,S1_23_0,S1_23_1,S1_23_2);
   assign S2_23_1 = S1_23_3;
   FA fa77 (S2_25_2,S2_24_0,S1_24_0,S1_24_1,S1_24_2);
   assign S2_24_1 = S1_24_3;
   FA fa78 (S2_26_2,S2_25_0,S1_25_0,S1_25_1,S1_25_2);
   assign S2_25_1 = S1_25_3;
   FA fa79 (S2_27_2,S2_26_0,S1_26_0,S1_26_1,S1_26_2);
   assign S2_26_1 = S1_26_3;
   FA fa80 (S2_28_1,S2_27_0,S1_27_0,S1_27_1,S1_27_2);
   assign S2_27_1 = S1_27_3;
   FA fa81 (S2_29_1,S2_28_0,S1_28_0,S1_28_1,S1_28_2);
   HA ha18 (S2_30_1,S2_29_0,S1_29_0,S1_29_1);
   HA ha19 (S2_31_1,S2_30_0,S1_30_0,S1_30_1);
   HA ha20 (S2_31_Carry_0,S2_31_0,S1_31_0,S1_31_1);
   // ==================== Stage3 ====================
   assign S3_0_0 = S2_0_0;
   assign S3_1_0 = S2_1_0;
   HA ha21 (S3_3_1,S3_2_0,S2_2_0,S2_2_1);
   assign S3_3_0 = S2_3_0;
   HA ha22 (S3_5_1,S3_4_0,S2_4_0,S2_4_1);
   HA ha23 (S3_6_1,S3_5_0,S2_5_0,S2_5_1);
   HA ha24 (S3_7_1,S3_6_0,S2_6_0,S2_6_1);
   FA fa82 (S3_8_1,S3_7_0,S2_7_0,S2_7_1,S2_7_2);
   HA ha25 (S3_9_1,S3_8_0,S2_8_0,S2_8_1);
   FA fa83 (S3_10_1,S3_9_0,S2_9_0,S2_9_1,S2_9_2);
   FA fa84 (S3_11_2,S3_10_0,S2_10_0,S2_10_1,S2_10_2);
   FA fa85 (S3_12_1,S3_11_0,S2_11_0,S2_11_1,S2_11_2);
   assign S3_11_1 = S2_11_3;
   FA fa86 (S3_13_2,S3_12_0,S2_12_0,S2_12_1,S2_12_2);
   FA fa87 (S3_14_2,S3_13_0,S2_13_0,S2_13_1,S2_13_2);
   assign S3_13_1 = S2_13_3;
   FA fa88 (S3_15_2,S3_14_0,S2_14_0,S2_14_1,S2_14_2);
   assign S3_14_1 = S2_14_3;
   FA fa89 (S3_16_2,S3_15_0,S2_15_0,S2_15_1,S2_15_2);
   assign S3_15_1 = S2_15_3;
   FA fa90 (S3_17_2,S3_16_0,S2_16_0,S2_16_1,S2_16_2);
   assign S3_16_1 = S2_16_3;
   FA fa91 (S3_18_2,S3_17_0,S2_17_0,S2_17_1,S2_17_2);
   assign S3_17_1 = S2_17_3;
   FA fa92 (S3_19_2,S3_18_0,S2_18_0,S2_18_1,S2_18_2);
   assign S3_18_1 = S2_18_3;
   FA fa93 (S3_20_2,S3_19_0,S2_19_0,S2_19_1,S2_19_2);
   assign S3_19_1 = S2_19_3;
   FA fa94 (S3_21_2,S3_20_0,S2_20_0,S2_20_1,S2_20_2);
   assign S3_20_1 = S2_20_3;
   FA fa95 (S3_22_2,S3_21_0,S2_21_0,S2_21_1,S2_21_2);
   assign S3_21_1 = S2_21_3;
   FA fa96 (S3_23_2,S3_22_0,S2_22_0,S2_22_1,S2_22_2);
   assign S3_22_1 = S2_22_3;
   FA fa97 (S3_24_1,S3_23_0,S2_23_0,S2_23_1,S2_23_2);
   assign S3_23_1 = S2_23_3;
   FA fa98 (S3_25_1,S3_24_0,S2_24_0,S2_24_1,S2_24_2);
   FA fa99 (S3_26_1,S3_25_0,S2_25_0,S2_25_1,S2_25_2);
   FA fa100 (S3_27_1,S3_26_0,S2_26_0,S2_26_1,S2_26_2);
   FA fa101 (S3_28_1,S3_27_0,S2_27_0,S2_27_1,S2_27_2);
   HA ha26 (S3_29_1,S3_28_0,S2_28_0,S2_28_1);
   HA ha27 (S3_30_1,S3_29_0,S2_29_0,S2_29_1);
   HA ha28 (S3_31_1,S3_30_0,S2_30_0,S2_30_1);
   HA ha29 (S3_31_Carry_0,S3_31_0,S2_31_0,S2_31_1);
   // ==================== Stage4 ====================
   assign S4_0_0 = S3_0_0;
   assign S4_1_0 = S3_1_0;
   assign S4_2_0 = S3_2_0;
   HA ha30 (S4_4_1,S4_3_0,S3_3_0,S3_3_1);
   assign S4_4_0 = S3_4_0;
   HA ha31 (S4_6_1,S4_5_0,S3_5_0,S3_5_1);
   HA ha32 (S4_7_1,S4_6_0,S3_6_0,S3_6_1);
   HA ha33 (S4_8_1,S4_7_0,S3_7_0,S3_7_1);
   HA ha34 (S4_9_1,S4_8_0,S3_8_0,S3_8_1);
   HA ha35 (S4_10_1,S4_9_0,S3_9_0,S3_9_1);
   HA ha36 (S4_11_1,S4_10_0,S3_10_0,S3_10_1);
   FA fa102 (S4_12_1,S4_11_0,S3_11_0,S3_11_1,S3_11_2);
   HA ha37 (S4_13_1,S4_12_0,S3_12_0,S3_12_1);
   FA fa103 (S4_14_1,S4_13_0,S3_13_0,S3_13_1,S3_13_2);
   FA fa104 (S4_15_1,S4_14_0,S3_14_0,S3_14_1,S3_14_2);
   FA fa105 (S4_16_1,S4_15_0,S3_15_0,S3_15_1,S3_15_2);
   FA fa106 (S4_17_1,S4_16_0,S3_16_0,S3_16_1,S3_16_2);
   FA fa107 (S4_18_1,S4_17_0,S3_17_0,S3_17_1,S3_17_2);
   FA fa108 (S4_19_1,S4_18_0,S3_18_0,S3_18_1,S3_18_2);
   FA fa109 (S4_20_1,S4_19_0,S3_19_0,S3_19_1,S3_19_2);
   FA fa110 (S4_21_1,S4_20_0,S3_20_0,S3_20_1,S3_20_2);
   FA fa111 (S4_22_1,S4_21_0,S3_21_0,S3_21_1,S3_21_2);
   FA fa112 (S4_23_1,S4_22_0,S3_22_0,S3_22_1,S3_22_2);
   FA fa113 (S4_24_1,S4_23_0,S3_23_0,S3_23_1,S3_23_2);
   HA ha38 (S4_25_1,S4_24_0,S3_24_0,S3_24_1);
   HA ha39 (S4_26_1,S4_25_0,S3_25_0,S3_25_1);
   HA ha40 (S4_27_1,S4_26_0,S3_26_0,S3_26_1);
   HA ha41 (S4_28_1,S4_27_0,S3_27_0,S3_27_1);
   HA ha42 (S4_29_1,S4_28_0,S3_28_0,S3_28_1);
   HA ha43 (S4_30_1,S4_29_0,S3_29_0,S3_29_1);
   HA ha44 (S4_31_1,S4_30_0,S3_30_0,S3_30_1);
   HA ha45 (S4_31_Carry_0,S4_31_0,S3_31_0,S3_31_1);
   // ==================== Final 2 PPs ====================
   assign final_pp0 = {S4_31_0,S4_30_0,S4_29_0,S4_28_0,S4_27_0,S4_26_0,S4_25_0,S4_24_0,S4_23_0,S4_22_0,S4_21_0,S4_20_0,S4_19_0,S4_18_0,S4_17_0,S4_16_0,S4_15_0,S4_14_0,S4_13_0,S4_12_0,S4_11_0,S4_10_0,S4_9_0,S4_8_0,S4_7_0,S4_6_0,S4_5_0,S4_4_0,S4_3_0,S4_2_0,S4_1_0,S4_0_0};
   assign final_pp1 = {S4_31_1,S4_30_1,S4_29_1,S4_28_1,S4_27_1,S4_26_1,S4_25_1,S4_24_1,S4_23_1,S4_22_1,S4_21_1,S4_20_1,S4_19_1,S4_18_1,S4_17_1,S4_16_1,S4_15_1,S4_14_1,S4_13_1,S4_12_1,S4_11_1,S4_10_1,S4_9_1,S4_8_1,S4_7_1,S4_6_1,1'b0,S4_4_1,1'b0,1'b0,1'b0,1'b0};

   // -------------------- total 113 FAs and 45 HAs --------------------
   
   // ==================== the final CPA ====================
   assign o_product = final_pp0 + final_pp1;
   
endmodule // multiply_16x16_8x8

